﻿#include "websoketserver.h"
#include <QByteArray>
#include <QJsonDocument>
#include <QLoggingCategory>
#include <QTimer>
#include <QNetworkCookieJar>

//根据编译条件是否为DEBUG，设置服务器地址
//#ifdef QT_NO_DEBUG
    const QString LOGIN_ADDRESS = QStringLiteral("http://www.cassmall.com/cassec-websocket/login");
    const QString SERVER_ADDRESS = QStringLiteral("ws://www.cassmall.com/cassec-websocket/websocket");
//#else
//    const QString LOGIN_ADDRESS = QStringLiteral("http://192.168.29.29:8009/cassec-websocket/login");
//    const QString SERVER_ADDRESS = QStringLiteral("ws://192.168.29.29:8009/cassec-websocket/websocket");
//#endif


//断线重连次数
const int MAX_RETRY_TIMES = 10;

WebSocketServer::WebSocketServer(QObject *parent) : QObject(parent)
{
    retried = 0;
    isLogin = false;
    manager = new QNetworkAccessManager(this);
    manager->setCookieJar(&cookieJar);
    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));
    connect(&websoket,SIGNAL(connected()),this,SLOT(doConnnected()));
    connect(&websoket,SIGNAL(disconnected()),this,SLOT(doDisconnected()));
    connect(&websoket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(doError(QAbstractSocket::SocketError)));
    connect(&websoket,SIGNAL(textMessageReceived(QString)),this,SLOT(doTextMessage(QString)));
}


void WebSocketServer::setUserPassword(const QString &username, const QString &password)
{
    this->username = username;
    this->password = password;
}

QString WebSocketServer::getErrorMessage() const
{
    return errorMessage;
}

QString WebSocketServer::getToken() const
{
    return token;
}

void WebSocketServer::setToken(const QString &value)
{
    token = value;
}

QString WebSocketServer::getUsername() const
{
    return username;
}

void WebSocketServer::connectServer()
{
    qDebug()<<"connecting..";
    QNetworkRequest request;
    request.setUrl(QUrl(SERVER_ADDRESS));
    request.setHeader(QNetworkRequest::CookieHeader,QVariant::fromValue(cookieJar.getCookies()));
    websoket.open(request);
    retried++;
}

void WebSocketServer::login(const QString &username, const QString &password)
{
    retried = 0;
    //connectServer();
    this->setUserPassword(username,password);
    QNetworkRequest request;
    request.setUrl(QUrl(LOGIN_ADDRESS));
    request.setRawHeader("Content-Type","application/x-www-form-urlencoded");
    QByteArray postData = QString("username="+username+"&password="+password).toLatin1();
    manager->post(request,postData);
}

//websocket建立连接后，发送连接成功信号
void WebSocketServer::doConnnected()
{
    qDebug()<<"connect success";
    retried = 0;
    emit connectSuccess();
}

//断开websocket连接后重试
void WebSocketServer::doDisconnected()
{
    qDebug()<<"retried:" << retried;
    qDebug()<<"currentError:"<<currentError;

    if(retried >= MAX_RETRY_TIMES){
        emit connectFailed(this->errorMessage);
        return;
    }
    if(currentError == QAbstractSocket::RemoteHostClosedError){
        connectServer();
        return;
    }

    qDebug()<<"retry after 5secs..";
    QTimer::singleShot(5000,this,SLOT(connectServer()));
}

void WebSocketServer::doError(QAbstractSocket::SocketError error)
{
    //触发disconneced
    websoket.abort();

    currentError = error;
    if(error != QAbstractSocket::RemoteHostClosedError){
        //记录错误
        QMessageLogger().critical(QLoggingCategory("websocket"))<<error;
        this->errorMessage = QStringLiteral("无法连接到消息服务器");
    }
}

void WebSocketServer::doTextMessage(const QString &message)
{
    qDebug()<<message;
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(message.toLocal8Bit(),&error);
    if (error.error == QJsonParseError::NoError) {
        // 如果是json对象，转换成map
        if(doc.isObject()){
            QVariantMap result = doc.toVariant().toMap();
            qDebug()<<result;

            QString type = result["type"].toString();
            if(type == "update"){
                emit updateRequest();
            }

            int count = result["count"].toInt();
            qDebug()<<"count"<<count;
            QString link = result["link"].toString();

            QString contentTmp = QStringLiteral("您有 <b style='color:#E73A3F;font-size:20px;'>") + QString::number(count) + QStringLiteral("</b> 笔新订单，请尽快处理!");
            emit messageRecived(contentTmp,link);
        }

    }
    qDebug()<<message;
}

//登录响应成功,连接服务器
void WebSocketServer::replyFinished(QNetworkReply *reply)
{
    if(reply->error()){
        QMessageLogger().warning(QLoggingCategory("websocket"))<<reply->errorString();
        errorMessage = QStringLiteral("连接服务器失败");
        qDebug()<< reply->errorString();
        emit connectFailed(errorMessage);
        reply->deleteLater();
        return;
    }
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    //如果状态码大于300，登录失败返回错误信息
    if( statusCode > 300 ){
        QString errorStr = QString(reply->readAll());
        emit connectFailed(errorStr);
        return;
    }

    QString loginMsg = reply->readAll();
    qDebug()<<"服务器登录："<<loginMsg;
    this->setToken(loginMsg);

    qDebug()<<reply->rawHeaderPairs();
    qDebug()<<cookieJar.getCookies();
    reply->deleteLater();

    //连接websocket服务器
    connectServer();
}
